<template>
  <article id="article" class="article" :class="{ mobile: isMobile }">
    <div ref="detail" class="detail">
      <transition name="module">
        <div
          v-if="!isFetching"
          class="oirigin"
          :class="{
            self: !article.origin,
            other: article.origin === constants.OriginState.Reprint,
            hybrid: article.origin === constants.OriginState.Hybrid
          }"
        >
          <span v-if="!article.origin" v-text="$i18n.text.origin.original" />
          <span
            v-else-if="article.origin === constants.OriginState.Reprint"
            v-text="$i18n.text.origin.reprint"
          />
          <span
            v-else-if="article.origin === constants.OriginState.Hybrid"
            v-text="$i18n.text.origin.hybrid"
          />
        </div>
      </transition>
      <transition name="module" mode="out-in" @after-enter="contentAnimateDone">
        <div v-if="isFetching" key="skeleton" class="skeleton">
          <no-ssr>
            <skeleton-line class="title" />
            <skeleton-paragraph
              class="content"
              :lines="9"
              line-height="1.2em"
            />
          </no-ssr>
        </div>
        <div v-else key="knowledge" class="knowledge">
          <h2 class="title">
            {{ article.title }}
          </h2>
          <div
            :id="contentElementIds.content"
            class="content"
            v-html="articleContent"
          />
          <transition
            name="module"
            mode="out-in"
            @after-enter="readMoreAnimateDone"
          >
            <div v-if="isCanReadMore" key="readmore-btn" class="readmore">
              <button
                class="readmore-btn"
                :disabled="isReadMoreLoading"
                @click="readMore()"
              >
                <span>{{
                  isReadMoreLoading
                    ? $i18n.text.article.rendering
                    : $i18n.text.article.readAll
                }}</span>
                <i class="iconfont icon-next-bottom" />
              </button>
            </div>
            <div
              v-else-if="article.isRenderedFullContent"
              :id="contentElementIds.moreContent"
              key="more-content"
              class="content"
              v-html="articleMoreContent"
            />
          </transition>
        </div>
      </transition>
    </div>
    <no-ssr>
      <div class="mammon">
        <transition name="module" mode="out-in">
          <skeleton-paragraph
            v-if="isFetching"
            key="skeleton"
            class="mammon-skeleton"
            :lines="4"
            line-height="1em"
          />
          <adsense-article v-else-if="renderAd" key="adsense" />
        </transition>
      </div>
    </no-ssr>
    <div class="share">
      <transition name="module" mode="out-in">
        <div v-if="isFetching" key="skeleton" class="skeleton">
          <skeleton-base
            v-for="item in isMobile ? 3 : 10"
            :key="item"
            :style="{
              width: `calc((100% - (1em * ${isMobile ? 2 : 9})) / ${
                isMobile ? 3 : 10
              })`
            }"
            :radius="0"
          />
        </div>
<!--        <share-box v-else key="share" class="article" />-->
      </transition>
    </div>
    <transition name="module" mode="out-in">
      <div v-if="isFetching" key="skeleton" class="metas">
        <skeleton-paragraph :align="true" :lines="4" line-height="1.2em" />
      </div>
      <div v-else key="metas" class="metas">
        <p v-if="isEnLang" class="item">
          <span>Article created at</span>
          <span>&nbsp;</span>
          <nuxt-link
            :title="getDateTitle(article.createTime)"
            :to="getDateLink(article.createTime)"
          >
            <span>{{ getDateTitle(article.createTime) }}</span>
          </nuxt-link>
          <span>&nbsp;in category&nbsp;</span>
          <nuxt-link
            :key="article.categoryId"
            :to="`/category/${article.category.slug}`"
            :title="article.category.description || article.category.name"
          >
            <span>{{ article.category.slug }}</span>
          </nuxt-link>
          <span v-if="article.categoryId == null">no catgory</span>
          <span>,&nbsp;&nbsp;</span>
          <span>{{ article.lookCount || 0 }}</span>
          <span>&nbsp;Views</span>
        </p>
        <p v-else class="item">
          <span>本文于</span>
          <span>&nbsp;</span>
          <nuxt-link
            :title="getDateTitle(article.createTime)"
            :to="getDateLink(article.createTime)"
          >
            <span>{{ getDateTitle(article.createTime) }}</span>
          </nuxt-link>
          <span>&nbsp;发布在&nbsp;</span>
          <span v-if="!article.categoryId != null">
            <nuxt-link
              :to="`/category/${article.category.slug}`"
              :title="article.category.description || article.category.name"
            >
              <span>{{ article.category.name }}</span>
            </nuxt-link>
          </span>
          <span v-else>未知</span>
          <span>&nbsp;分类下，当前已被围观&nbsp;</span>
          <span>{{ article.lookCount || 0 }}</span>
          <span>&nbsp;次</span>
        </p>
        <p class="item">
          <span class="title" :class="language">{{
            isEnLang ? 'Related tags:' : '相关标签：'
          }}</span>
          <span v-if="!article.tag.length" v-text="$i18n.text.tag.empty" />
          <span v-for="(tag, index) in article.tag" :key="index">
            <nuxt-link
              :to="`/tag/${tag.slug}`"
              :title="tag.description || tag.name"
            >
              <span>{{ isEnLang ? tag.slug : tag.name }}</span>
            </nuxt-link>
            <span v-if="article.tag.length && article.tag[index + 1]">、</span>
          </span>
        </p>
        <p class="item">
          <span class="title" :class="language">{{
            isEnLang ? 'Article Address:' : '永久地址：'
          }}</span>
          <span class="site-url" @click="copyArticleUrl">
            <span>{{ appOption.siteWebUrl }}/article/{{ article.id }}</span>
          </span>
        </p>
        <div class="item">
          <span class="title" :class="language">{{
            isEnLang ? 'Copyright Clarify:' : '版权声明：'
          }}</span>
          <span v-if="!isEnLang">
            <span>自由转载-署名-非商业性使用</span>
            <span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
          </span>
          <a
            target="_blank"
            rel="external nofollow noopenter"
            href="https://creativecommons.org/licenses/by-nc/3.0/cn/deed.zh"
          >Creative Commons BY-NC 3.0 CN</a>
        </div>
      </div>
    </transition>
    <transition name="module" mode="out-in">
      <div v-if="isFetching" key="skeleton" class="related">
        <skeleton-paragraph
          v-if="isMobile"
          class="skeleton"
          :lines="4"
          line-height="1em"
        />
        <ul v-else class="skeleton-list">
          <skeleton-base v-for="item in 4" :key="item" class="article" />
        </ul>
      </div>
      <div
        v-else-if="article.related && article.related.length"
        key="related"
        class="related"
      >
        <div
          v-if="!isMobile"
          v-swiper:swiper="swiperOption"
          class="article-list swiper"
        >
          <div class="swiper-wrapper">
            <div
              v-for="(article, index) in relatedArticles"
              :key="index"
              class="swiper-slide item"
            >
              <a
                v-if="article.ad"
                class="item-box filter"
                rel="external nofollow noopener"
                target="_blank"
                :class="{ 'motion-blur-horizontal-small': transitioning }"
                :href="article.link"
              >
                <img :src="article.img" class="thumb" :alt="article.title">
                <span class="title">{{ article.title }}</span>
              </a>
              <nuxt-link
                v-else
                class="item-box filter"
                :class="{ 'motion-blur-horizontal-small': transitioning }"
                :to="`/article/${article.id}`"
                :title="article.title"
              >
                <img
                  :src="getThumb(article.thumb)"
                  :alt="article.title"
                  class="thumb"
                >
                <span class="title">{{ article.title }}</span>
              </nuxt-link>
            </div>
          </div>
        </div>
        <ul v-else class="article-list">
          <li
            v-for="(article, index) in relatedArticles"
            :key="index"
            class="item"
          >
            <a
              v-if="article.ad"
              class="item-link"
              :href="article.link"
              rel="external nofollow noopener"
              target="_blank"
            >
              <span class="sign">《</span>
              <span class="title">{{ article.title }}</span>
              <span class="sign">》</span>
              <small class="tip">- 狠狠地阅读</small>
            </a>
            <nuxt-link
              v-else
              class="item-link"
              :to="`/article/${article.id}`"
              :title="`「 ${article.title} 」- 继续阅读`"
            >
              <span class="sign">《</span>
              <span class="title">{{ article.title }}</span>
              <span class="sign">》</span>
              <small class="tip">- 继续阅读</small>
            </nuxt-link>
          </li>
        </ul>
      </div>
    </transition>
    <div v-if="article && article.comment" class="comment">
      <comment-box
        :fetching="isFetching"
        :post-id="routeArticleId"
        :likes="article.loveCount"
      />
    </div>
  </article>
</template>

<script>
import { mapState } from 'vuex'
import { isBrowser } from '~/environment/esm'
import lozad from '~/plugins/lozad'
import marked from '~/plugins/marked'
// import ShareBox from '~/components/widget/share'

export default {
  name: 'ArticleDetail',
  components: {
    // ShareBox
  },
  validate({ params, store }) {
    return params.article_id && !isNaN(Number(params.article_id))
  },
  data() {
    return {
      transitioning: false,
      swiperOption: {
        setWrapperSize: true,
        simulateTouch: false,
        mousewheel: {
          sensitivity: 1
        },
        autoplay: {
          delay: 3500,
          disableOnInteraction: false
        },
        observeParents: true,
        grabCursor: true,
        slidesPerView: 'auto'
      },
      // lozadObserver: null,
      isReadMoreLoading: false,
      renderAd: true,
      contentElementIds: {
        content: 'article-content',
        moreContent: 'more-article-content'
      }
    }
  },
  computed: {
    ...mapState({
      constants: state => state.global.constants,
      language: state => state.global.language,
      tags: state => state.tag.data,
      imageExt: state => state.global.imageExt,
      article: state => state.article.detail.data,
      isFetching: state => state.article.detail.fetching,
      isMobile: state => state.global.isMobile,
      appOption: state => state.global.appOption.data
    }),
    isEnLang() {
      return this.$store.getters['global/isEnLang']
    },
    routeArticleId() {
      return Number(this.$route.params.article_id)
    },
    isContentTooMore() {
      const { content } = this.article
      return content && content.length > 13688
    },
    isCanReadMore() {
      return this.isContentTooMore && !this.article.isRenderedFullContent
    },
    moreContentIndex() {
      if (!this.isContentTooMore) {
        return null
      }
      // 坐标优先级：H4 -> H3 -> Code -> \n\n
      const shortContent = this.article.content.substring(0, 11688)
      const lastH4Index = shortContent.lastIndexOf('\n####')
      const lastH3Index = shortContent.lastIndexOf('\n###')
      const lastCodeIndex = shortContent.lastIndexOf('\n\n```')
      const lastLineIndex = shortContent.lastIndexOf('\n\n**')
      return Math.max(
        lastH4Index,
        lastH3Index,
        lastCodeIndex,
        lastLineIndex
      )
    },
    articleContent() {
      const { content } = this.article
      if (!content) {
        return ''
      }
      return marked(
        this.isContentTooMore
          // 渲染截断部分前半段
          ? content.substring(0, this.moreContentIndex)
          // 正常长度，正常渲染
          : content,
        this.tags,
        true
      )
    },
    articleMoreContent() {
      const { content } = this.article
      if (!content || !this.isContentTooMore) {
        return ''
      }
      return marked(
        content.substring(this.moreContentIndex, content.length),
        this.tags,
        true
      )
    },
    relatedArticles() {
      return [...this.article.related].slice(0, 10)
    }
  },
  fetch({ store, params, error }) {
    return Promise.all([
      store.dispatch('article/fetchDetail', params).catch(() => {
        error({ statusCode: 404, message: '众里寻他 我已不再' })
      }),
      store.dispatch('comment/fetchList', { post_id: params.article_id }),
      store.dispatch('global/fetchAppOption')
    ])
  },
  head() {
    const { article } = this
    return {
      title: article.title || '...',
      meta: [
        {
          hid: 'keywords',
          name: 'keywords',
          content:
            (article && article.keywords ? article.keywords : article.title) ||
            ''
        },
        {
          hid: 'description',
          name: 'description',
          content: article ? article.description : ''
        }
      ]
    }
  },
  mounted() {
    if (isBrowser) {
      this.observeLozad(this.contentElementIds.content)
    }
  },
  activated() {
    this.updateAd()
  },
  methods: {
    readMore() {
      this.isReadMoreLoading = true
      this.$nextTick(() => {
        setTimeout(() => {
          this.$store.commit('article/updateDetailRenderedState', true)
          this.isReadMoreLoading = false
        }, 0)
      })
    },
    updateAd() {
      this.renderAd = false
      this.$nextTick(() => {
        this.renderAd = true
      })
    },
    contentAnimateDone() {
      // console.log('contentAnimateDone')
      this.observeLozad(this.contentElementIds.content)
    },
    readMoreAnimateDone() {
      // console.log('readMoreAnimateDone')
      this.observeLozad(this.contentElementIds.moreContent)
    },
    observeLozad(elementId) {
      const contentElement = this.$refs.detail.querySelector(`#${elementId}`)
      const lozadElements =
        contentElement && contentElement.querySelectorAll('.lozad')
      if (!lozadElements || !lozadElements.length) {
        return false
      }
      // console.log('计算出的文档:', this.$refs.detail, contentElement, lozadElements)
      const lozadObserver = lozad(lozadElements, {
        loaded: element => element.classList.add('loaded')
      })
      lozadObserver.observe()
      // console.log('重新监听 observer', lozadObserver)
    },
    copyArticleUrl() {
      if (this.article.title) {
        this.$root.$copyToClipboard(
          `${this.appOption.siteWebUrl}/article/${this.article.id}`
        )
      }
    },
    getThumb(thumb) {
      return thumb
        ? `${thumb}?imageView2/1/w/300/h/230/format/${this.imageExt}/interlace/1/q/80|imageslim` : `${this.appOption.siteWebUrl}/images/thumb-releted.jpg`
    },
    getDateTitle(date) {
      if (!date) {
        return date
      }
      date = new Date(date)
      const am = this.isEnLang ? 'AM' : '上午'
      const pm = this.isEnLang ? 'PM' : '下午'
      const year = date.getFullYear()
      const month = date.getMonth() + 1
      const day = date.getDate()
      const meridiem = date.getHours() > 11 ? pm : am
      return `${year}/${month}/${day} ${meridiem}`
    },
    getDateLink(date) {
      if (!date) {
        return date
      }
      date = new Date(date)
      const year = date.getFullYear()
      let month = (date.getMonth() + 1).toString()
      let day = date.getDate().toString()
      month = month.length === 1 ? `0${month}` : month
      day = day.length === 1 ? `0${day}` : day
      return `/date/${year}-${month}-${day}`
    },
    handleSwiperTransitionStart() {
      this.transitioning = true
    },
    handleSwiperTransitionEnd() {
      this.transitioning = false
    },
    imgReplace(content) {
      return content.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(match, capture) {
        return `
                        <img
                          class="lozad"
                          data-src="${capture}"
                          title="${capture}"
                          alt="${capture}"
                          onclick="if (window.utils) window.utils.openImgPopup('${capture}')"
                        />
                      `
      })
    }
  }
}
</script>

<style lang="scss">
.article {
  &.mobile {
    > .metas {
      line-height: 2.3em;

      > .item {
        margin: 0;
        padding: 0;
        border: none;

        > .title.en {
          width: auto;
          margin-right: 1rem;
        }
      }
    }

    > .related {
      height: auto;

      > .article-list {
        padding: 0;
        margin: 0;
        list-style: none;
        overflow: hidden;
        opacity: 0.9;

        > .item {
          > .item-link {
            display: flex;
            width: 100%;
            height: 2.2em;
            line-height: 2.2em;

            > .title {
              max-width: 70%;
              display: inline-block;
              @include text-overflow();
            }

            > .tip {
              display: inline-block;
            }
          }
        }
      }
    }

    > .detail {
      > .oirigin {
        font-size: $font-size-base;
      }

      > .knowledge {
        > .content {
          pre {
            padding-left: 0;

            > .code-lines {
              display: none;
            }
          }
        }
      }
    }
  }

  > .detail,
  > .mammon,
  > .metas,
  > .related {
    margin-bottom: 1em;
    background-color: $module-bg;
  }

  > .mammon {
    .mammon-skeleton {
      padding: 1em;
    }
  }

  > .detail {
    padding: 1em 2em;
    position: relative;
    overflow: hidden;
    height: auto;
    transition: height 0.25s;

    > .skeleton {
      .title {
        width: 60%;
        height: 26px;
        margin: 2rem auto;
      }

      .content {
        margin-top: 3rem;
        margin-bottom: 1rem;
      }
    }

    > .oirigin {
      position: absolute;
      top: -0.9rem;
      left: -2.4rem;
      transform: rotate(-45deg);
      width: 7rem;
      height: 4rem;
      line-height: 5.8rem;
      text-align: center;
      transform-origin: center;
      color: $white;
      font-weight: bold;
      font-size: $font-size-small;
      text-transform: uppercase;

      &.self {
        background-color: rgba($accent, 0.8);
      }

      &.other {
        background-color: rgba($red, 0.8);
      }

      &.hybrid {
        background-color: rgba($primary, 0.8);
      }
    }

    > .knowledge {
      > .title {
        text-align: center;
        margin: 1em 0 1.5em 0;
        font-weight: 700;
      }

      > .content {
        iframe {
          width: 100%;
          margin-bottom: 1em;
          background-color: black;
        }

        a {
          font-weight: bold;
          margin: 0 0.1em;

          &.image-link {
            margin: 0;
          }

          &:hover {
            text-decoration: underline;
          }
        }

        img {
          max-width: 100%;
          position: relative;
          margin: 0 auto;
          display: block;
          text-align: center;
          border-radius: $radius;
          border: 0.5rem solid $module-hover-bg;
          transition: all 0.25s;
          opacity: 0.9;
          cursor: pointer;

          // &::after {
          //   content: "...";
          //   height: 100%;
          //   width: 100%;
          //   position: absolute;
          //   left: 0;
          //   top: 0;
          // }

          &:hover {
            opacity: 1;
            transition: all 0.25s;
          }
        }

        p {
          line-height: 2.2em;
          text-indent: 2em;
          margin-bottom: 1em;

          &.text-center {
            text-align: center;
          }

          &.text-right {
            text-align: right;
          }
        }

        h1,
        h2,
        h3,
        h4,
        h5,
        h6 {
          margin: 1.5rem 0;
          padding-left: 0;
          line-height: 1.8em;
          font-weight: 700;
          text-indent: 0;
        }

        blockquote {
          p {
            // text-indent: 0em;

            &:last-child {
              margin-bottom: 0;
            }
          }
        }

        ul {
          list-style-type: square;
        }

        ul,
        ol {
          > li {
            line-height: 1.8em;
            padding: 0.5em 0.8em;

            &:hover {
              background-color: $module-hover-bg;
            }

            > p {
              text-indent: 0;
            }

            > ul {
              &:last-child {
                margin-bottom: 0;
              }
            }
          }
        }

        code {
          color: #bd4147;
          padding: 0.3em 0.5em;
          margin: 0 0.5em;
          border-radius: $radius;
          background-color: $module-hover-bg;
        }

        pre {
          $code-line-height: 2.8em;
          $code-line-width: 2.5em;
          $code-line-line-height: 1.6em;
          display: block;
          position: relative;
          overflow: hidden;
          margin-bottom: 1em;
          padding-left: $code-line-width;
          background-color: rgba(0, 0, 0, 0.8);

          &:before {
            color: white;
            content: attr(data-lang) ' CODE';
            height: $code-line-height;
            line-height: $code-line-height;
            font-size: 1em;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            font-weight: 700;
            background-color: rgba(68, 68, 68, 0.9);
            display: block;
            text-transform: uppercase;
            text-align: center;
          }

          > .code-lines {
            position: absolute;
            left: 0;
            top: $code-line-height;
            margin: 0;
            padding: 1em 0;
            width: $code-line-width;
            height: calc(100% - #{$code-line-height});
            text-align: center;
            background-color: rgba(0, 0, 0, 0.2);

            > .code-line-number {
              padding: 0;
              position: relative;
              list-style-type: none;
              line-height: $code-line-line-height;
              transition: background-color 0.05s;

              &:hover {
                &:before {
                  display: block;
                  opacity: 1;
                  visibility: visible;
                }
              }

              &:before {
                content: '';
                height: $code-line-line-height;
                position: absolute;
                top: 0;
                left: $code-line-width;
                width: 66em;
                background-color: rgba(154, 154, 154, 0.2);
                display: none;
                visibility: hidden;
                opacity: 0;
              }
            }
          }

          > code {
            margin: 0;
            padding: 1em;
            // padding-top: $code-line-height + 1em;
            float: left;
            width: 100%;
            height: 100%;
            display: block;
            line-height: $code-line-line-height;
            color: rgba(255, 255, 255, 0.87);
            background-color: transparent;
          }
        }
      }

      @keyframes readmorebtn {
        0% {
          transform: translate3d(0, 0, 0);
          background-color: $module-hover-bg;
        }
        25% {
          transform: translate3d(0, 0.5rem, 0);
          background-color: $primary;
          color: white;
        }
        50% {
          transform: translate3d(0, 0, 0);
          background-color: $module-hover-bg;
        }
        75% {
          transform: translate3d(0, 0.5rem, 0);
          background-color: $primary;
          color: white;
        }
        100% {
          transform: translate3d(0, 0, 0);
          background-color: $module-hover-bg;
        }
      }

      > .readmore {
        width: 100%;
        display: flex;
        justify-content: center;
        margin-bottom: 0.8rem;

        > .readmore-btn {
          width: 80%;
          text-align: center;
          height: 3rem;
          line-height: 3rem;
          background-color: $module-hover-bg;
          animation: readmorebtn 4s linear infinite;

          &[disabled] {
            cursor: no-drop;
          }

          &:hover {
            background-color: $primary !important;
            color: white !important;
          }

          > .iconfont {
            margin-left: 0.5rem;
          }
        }
      }
    }
  }

  .share {
    padding: 1em;
    margin-bottom: 1em;
    background-color: $module-bg;

    > .skeleton {
      display: flex;
      justify-content: space-between;
      height: 3rem;
    }
  }

  > .metas {
    padding: 1em;

    > .item {
      border-left: solid 0.5em $body-bg;
      padding-left: 1rem;
      word-break: break-all;

      a:hover {
        text-decoration: underline;
      }

      > .title.en {
        width: 11rem;
        display: inline-block;
      }

      .site-url {
        text-decoration: underline;
        cursor: pointer;
        color: $link-color;

        &:hover {
          color: $link-hover-color;
        }
      }
    }
  }

  > .related {
    padding: 1em 0;
    border-width: 0 1em;
    border-color: transparent;
    overflow: hidden;
    height: 10em;

    > .skeleton-list {
      padding: 0;
      margin: 0;
      height: 100%;
      overflow: hidden;
      display: flex;

      .article {
        width: calc((100% - 2rem) / 4);
        margin-right: 1rem;

        &:last-child {
          margin-right: 0;
        }
      }
    }

    > .swiper.article-list {
      > .swiper-wrapper {
        height: 8em;
        overflow: hidden;

        > .swiper-slide.item {
          width: auto;
          margin-right: 1rem;

          &:last-child {
            margin-right: 0;
          }

          > .item-box {
            display: block;
            position: relative;
            overflow: hidden;
            width: auto;
            height: 100%;
            opacity: 0.8;

            &:hover {
              .thumb {
                opacity: 1;
                @include css3-prefix(transform, scale(1.1));
                @include css3-prefix(transition, all 0.88s);
              }

              > .title {
                opacity: 1;
              }
            }

            > .thumb {
              width: auto;
              height: 100%;
              @include css3-prefix(transform, scale(1));
              @include css3-prefix(transition, all 0.88s);
            }

            > .title {
              position: absolute;
              bottom: 0;
              left: 0;
              width: calc(100% - 1em);
              height: 2em;
              line-height: 2em;
              background-color: $module-hover-bg-darken-10;
              padding: 0 0.5em;
              color: $white;
              opacity: 0.4;
              font-size: 0.9em;
              text-align: center;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
            }
          }
        }
      }
    }
  }
}
</style>
